package cn.anquing.pattern.proxyPattern.jdkProxy.yuanli;

import org.apache.commons.io.FileUtils;

import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;


/**
 * JDK动态代理的思路
 * 实现功能：通过Proxy的newProxyInstance返回代理对象
 * 1、声明段源码（动态产生代理）
 * 2、编译源码（JDK Compiler API），产生新的类（代理类）
 * 3、将这个类load到内存中，产生新的对象（代理对象）
 * 4、return 代理对象
 */
public class Proxy {

    public static Object newProxyInstance(Class infce,InvocationHandler h) throws Exception {

        //1、声明段源码（动态产生代理）
        String rt = "\r\n";
        String methodStr = "";

        for(Method m : infce.getMethods()){

          methodStr="    @Override"+rt+
                    "     public void "+m.getName()+"() {"+rt+
                    "       try{"+rt+
                    "         Method md = "+infce.getName()+".class.getMethod(\""+m.getName()+"\");"+rt+
                    "         h.invoke(this,md);"+rt+
                    "       }catch(Exception e){e.printStackTrace();}"+rt+
                    "     }";

        }
        String str =
        "package cn.anquing.pattern.proxyPattern.jdkProxy.yuanli;"+rt+
        "import cn.anquing.pattern.proxyPattern.jdkProxy.yuanli.InvocationHandler;"+rt+
        "import java.lang.reflect.Method;"+rt+
        "public class $Proxy0 implements "+infce.getName()+" {"+rt+
        "    public $Proxy0(InvocationHandler h) {"+rt+
        "        super();"+rt+
        "        this.h = h;"+rt+
        "    }"+rt+
        "    private InvocationHandler h;"+rt+
              methodStr+rt+
        "}";
        //产生代理类java文件
        String fileName = System.getProperty("user.dir")+"/target/classes/cn/anquing/pattern/proxyPattern/jdkProxy/yuanli/$Proxy0.java";
        //System.out.println("path:"+fileName);
        File file = new File(fileName);
        FileUtils.writeStringToFile(file,str);

        //2、编译源码（JDK Compiler API），产生新的类（代理类）
        //拿到编译器
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        //文件管理者
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
        //获取文件
        Iterable units = fileManager.getJavaFileObjects(fileName);
        //编译任务
        JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, null, null, units);
        task.call();
        fileManager.close();
        //3、将这个类load到内存中，产生新的对象（代理对象）
        ClassLoader classLoader = ClassLoader.getSystemClassLoader();
        Class<?> c = classLoader.loadClass("cn.anquing.pattern.proxyPattern.jdkProxy.yuanli.$Proxy0");
        System.out.println("代理类的类名："+c.getName());
        //4、return 代理对象
        Constructor constructor = c.getConstructor(InvocationHandler.class);
        return constructor.newInstance(h);

    }

}
